﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace XNAGuiLib
{

    public class TextObject
    {
        #region Field - Position
        protected Vector2 _position;
        /// <summary>
        /// gets or sets TextObjects position on screen
        /// </summary>
        public Vector2 Position
        {
            get
            {
                return _position;
            }
            set
            {
                _position = value;
            }
        }
        #endregion

        #region Field - RelativePosition
        protected Vector2 _relativePosition;
        /// <summary>
        /// gets or sets TextObjects position on screen
        /// </summary>
        public Vector2 RelativePosition
        {
            get
            {
                return _relativePosition;
            }
            set
            {
                _relativePosition = value;
            }
        }
        #endregion

        #region Field - Bounds
        protected Vector2 _bounds;
        /// <summary>
        /// gets or sets the bounds inside which the Content should be drawn (ZeroVector2 for no bounds)
        /// </summary>
        public Vector2 Bounds
        {
            get
            {
                return _bounds;
            }
            set
            {
                _bounds = value;
            }
        }
        #endregion

        #region Field - Width
        /// <summary>
        /// gets or sets TextObjects Width
        /// </summary>
        public float Width
        {
            get
            {
                return _bounds.X;
            }
            set
            {
                _bounds = new Vector2(value, _bounds.Y);
            }
        }
        #endregion

        #region Field - Height
        /// <summary>
        /// gets or sets TextObjects Height
        /// </summary>
        public float Height
        {
            get
            {
                return _bounds.Y;
            }
            set
            {
                _bounds = new Vector2(_bounds.X, value);
            }
        }
        #endregion

        #region Field - X
        /// <summary>
        /// gets or sets x Position
        /// </summary>
        public float X
        {
            get
            {
                return _relativePosition.X;
            }
            set
            {
                _relativePosition = new Vector2(value, _relativePosition.Y);
            }
        }
        #endregion

        #region Field - Y
        /// <summary>
        /// gets or sets y Position
        /// </summary>
        public float Y
        {
            get
            {
                return _relativePosition.Y;
            }
            set
            {
                _relativePosition = new Vector2(_relativePosition.X, value);
            }
        }
        #endregion



        #region Field - Text
        protected string _text = "";
        /// <summary>
        /// gets or sets the TextObjects text
        /// </summary>
        public string Text
        {
            get
            {
                return _text;
            }
            set
            {
                _text = value;
            }
        }
        #endregion

        #region Field - Font
        protected SpriteFont _font;
        /// <summary>
        /// gets or sets the TextObjects SpriteFont
        /// </summary>
        public SpriteFont Font
        {
            get
            {
                return _font;
            }
            set
            {
                _font = value;
            }
        }
        #endregion

        #region Field - TextColor
        protected Color _textcolor = Color.Black;
        /// <summary>
        /// gets or sets the TextObjects TextColor
        /// </summary>
        public Color TextColor
        {
            get
            {
                return _textcolor;
            }
            set
            {
                _textcolor = value;
            }
        }
        #endregion

        #region Field - Scale
        protected float _scale = 1.0f;
        /// <summary>
        /// gets or sets the TextObject scale
        /// </summary>
        public float Scale
        {
            get
            {
                return _scale;
            }
            set
            {
                _scale = value;
            }
        }
        #endregion

        #region Field - Rotation
        protected float _rotation = 0.0f;
        /// <summary>
        /// gets or sets the TextObjects drawing rotation
        /// </summary>
        public float Rotation
        {
            get
            {
                return _rotation;
            }
            set
            {
                _rotation = value;
            }
        }
        #endregion

        #region Field - Origin
        private Vector2 _origin = new Vector2(0.0f, 0.0f);
        /// <summary>
        /// gets the Origin of this TextObject
        /// </summary>
        public Vector2 Origin
        {
            get
            {
                return _origin;
            }
        }
        #endregion

        #region Field - Effects
        protected SpriteEffects _effects = SpriteEffects.None;
        /// <summary>
        /// gets or sets the TextObjects SpriteEffects
        /// </summary>
        public SpriteEffects Effects
        {
            get
            {
                return _effects;
            }
            set
            {
                _effects = value;
            }
        }
        #endregion

        #region Field - LayerDepth
        protected float _layerDepth = 1.0f;
        /// <summary>
        /// gets or sets the TextObjects layer depth (between 0.0 and 1.0)
        /// </summary>
        public float LayerDepth
        {
            get
            {
                return _layerDepth;
            }
            set
            {
                _layerDepth = value;
            }
        }
        #endregion

        #region Field - Name
        protected string _name = "";
        /// <summary>
        /// gets or sets the TextureObjects name
        /// </summary>
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
        #endregion

        #region Field - Visible
        protected bool _visible = true;
        /// <summary>
        /// gets or sets if the Draw-Method should be executed
        /// </summary>
        public bool Visible
        {
            get
            {
                return _visible;
            }
            set
            {
                _visible = value;
            }
        }
        #endregion


        #region Constructor - TextObject(string text, SpriteFont font, string name, Vector2 relPosition, Vector2 bounds)
        public TextObject(string text, SpriteFont font, string name, Vector2 relPosition, Vector2 bounds)
        {
            // set the name
            _name = name;
            // set the Texture2D
            _text = text;
            // set the SpriteFont
            _font = font;
            // set the position (relative to the InterfaceObjects absolut position
            _relativePosition = relPosition;
            // set the bounds
            _bounds = bounds;
        }
        #endregion

        #region Constructor - TextObject(string text, SpriteFont font, string name, Vector2 relPosition, Vector2 bounds, bool visible)
        public TextObject(string text, SpriteFont font, string name, Vector2 relPosition, Vector2 bounds, bool visible)
        {
            // set the name
            _name = name;
            // set the Texture2D
            _text = text;
            // set the SpriteFont
            _font = font;
            // set the position (relative to the InterfaceObjects absolut position
            _relativePosition = relPosition;
            // set the bounds
            _bounds = bounds;
            // set if TextObject is visible
            _visible = visible;
        }
        #endregion


        #region Method - CheckCoordinates(MouseState ms)
        public bool CheckCoordinates(MouseState ms)
        {
            Vector2 size = this._font.MeasureString(_text);
            return new Rectangle((int)_position.X + (int)_relativePosition.X, (int)_position.Y + (int)_relativePosition.Y, (int)size.X, (int)size.Y).Intersects(new Rectangle(ms.X, ms.Y, 1, 1));
        }
        #endregion

        #region Method - Draw(SpriteBatch sprite)
        public void Draw(SpriteBatch sprite)
        {
            if (_visible)
            {
                string drawString = _text;

                DrawString(ref drawString);
                
                sprite.DrawString(_font, drawString, _position + _relativePosition, _textcolor, _rotation, _origin, _scale, _effects, _layerDepth);
            }
        }
        #endregion


        #region Private Method - BreakPosition(string value)s
        private int BreakPosition(string value)
        {
            int pos = 0;

            while (pos <= value.Length)
            {
                string sub = value.Substring(0, pos);
                if (_font.MeasureString(sub).X < _bounds.X)
                {
                    pos++;
                }
                else return pos;
            }

            return pos;
        }
        #endregion

        #region Private Method - DrawString(ref string drawString)
        private void DrawString(ref string drawString)
        {
            if (!_bounds.Equals(Statics.ZeroVector2) && _bounds != null)
            {
                // set size on x-Axxis of the current drawing string
                int xSize = (int)_font.MeasureString(drawString).X;
                // calculate number of times the string should be broken
                int times = xSize / (int)_bounds.X;

                // init list for the positions of the line-breaks
                List<int> breakPoss = new List<int>();
                // add the first break position to list
                breakPoss.Add(BreakPosition(drawString));

                // loop times - 1 for getting other breakpositions
                for (int i = 0; i < times - 1; i++)
                {
                    // add the next available break position
                    breakPoss.Add(BreakPosition(drawString.Substring(breakPoss[breakPoss.Count - 1])));
                }

                // init count for break position index
                int actBreakPos = 0;
                // loop throug break point list
                foreach (int pos in breakPoss)
                {
                    // set breakline position for current run
                    actBreakPos += pos;
                    // check if position is smaller/equals to the content length
                    if (actBreakPos <= _text.Length)
                        // set drawString to modified string with breakline
                        drawString = drawString.Insert(actBreakPos, "\n");
                    // increase by 1 (reason: \n)
                    actBreakPos += 1;
                }

            }
        }
        #endregion


        #region Override Method - ToString()
        public override string ToString()
        {
            return _name;
        }
        #endregion
    }
}